/*
 * QNoteGridView.h
 *
 *  Created on: Jul 1, 2010
 *      Author: alexr
 */

#ifndef QNOTEGRIDVIEW_H_
#define QNOTEGRIDVIEW_H_

#include <QGraphicsView>
#include <QGraphicsWidget>
#include <QWebView>
#include <QGraphicsGridLayout>
#include <MLabel>
#include <MButton>
#include <QGraphicsProxyWidget>
#include <QWebFrame>
#include <QImage>
#include <QApplication>
#include <QDesktopWidget>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsGridLayout>
#include "QvernoteAPI.h"
#include "QEnmlReader.h"
#include "QAbstractNoteView.h"
#include "QNotesView.h"
#include "ui/MClickableImage.h"
#include <QDebug>
#include <MLayout>
#include <MGridLayoutPolicy>
#include <MBasicLayoutAnimation>
#include "MeegoSupport.h"

class QNoteSnapshotWidget : public MWidget
{
	Q_OBJECT

public:
	QNoteSnapshotWidget(MWidget* parent = 0) : MWidget(parent), m_SnapshotImage(NULL), m_loadProgress(0), hasAttachment(false) {
            setObjectName("QNoteSnapshotWidget");
	}

	~QNoteSnapshotWidget() {
		//qDebug() << trUtf8("Deleting image");
		//delete m_SnapshotImage;
		//m_SnapshotImage = NULL;
	}

        QSizeF sizeHint (Qt::SizeHint which, const QSizeF & constraint = QSizeF()) const {
                return QSizeF(133, 100);
	}

        void paint(QPainter* painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0) {
		//painter->drawPixmap(QPoint(0, 0), m_Snapshot);
		painter->setRenderHint(QPainter::Antialiasing);

		if(m_SnapshotImage == NULL) {
			painter->setFont(QFont("Nokia Sans", 13));
			painter->drawText(QRectF(QPoint(0, 0), size()), Qt::AlignCenter, QString(trUtf8("Loading %1%")).arg(m_loadProgress));
		} else {
                    painter->drawPixmap(QPoint(0, 0), *m_SnapshotImage);
			if(hasAttachment)
				painter->drawPixmap(QRect(QPoint(size().width() - 32, 0), QSize(32, 32)), QPixmap(":/IconAdd/email_attachment.png"));
		}

                //painter->setPen(QPen(QBrush(palette().color(QPalette::Background)), 6));
                //painter->drawRoundedRect(QRectF(QPointF(0, 0), size()), 8, 8);
	}

	void render(Guid guid) {
		Note note;
		note.guid = guid;
		QvernoteAPI::Instance()->getNoteContent(note);
		enmlReader = new QEnmlReader(note);
		enmlReader->setLoadExternalReferences(false);
		enmlReader->parse();
		QObject::connect(enmlReader->getThumbnailCreator(), SIGNAL(snapshotReady()), this, SLOT(setNoteSnapshot()), Qt::QueuedConnection);
		QObject::connect(enmlReader->getThumbnailCreator(), SIGNAL(loadProgress(int)), this, SLOT(updateLoadProgress(int)));
		enmlReader->createThumbnail();
	}

	void render(QPixmap* thumbnail) {
                m_SnapshotImage = thumbnail;
	}

	void setAttachment(bool attachment) {
		hasAttachment = attachment;
	}

	QPixmap* getSnapshotImage() { return m_SnapshotImage; }

public slots:
	void setNoteSnapshot()
	{
		m_SnapshotImage = new QPixmap(enmlReader->getThumbnailCreator()->getThumbnail());
/*
                QPixmap wp(size().toSize());
                QPainter pp(&wp);
                pp.fillRect(wp.rect(), Qt::white);
                pp.setBrush(Qt::black);
                pp.drawRoundRect(wp.rect());
                setMask(wp.createMaskFromColor(Qt::white));
*/
		delete enmlReader;
		emit snapshotReady();
	}

	void updateLoadProgress(int p) {
		m_loadProgress = p;
		update();
	}

signals:
	void snapshotReady();

private:
        //QWebView*	m_WebView;
	QPixmap*	m_SnapshotImage;
	int			m_loadProgress;
	bool		hasAttachment;
	QEnmlReader* enmlReader;
};

class QNoteWidget : public MClickableImage
{
	Q_OBJECT

public:
        QNoteWidget(Note& note, MWidget* parent = 0) : MClickableImage(parent), m_Note(note) {
		layout = new QGraphicsGridLayout(this);
                layout->setContentsMargins(0, 4, 0, 4);
                layout->setSpacing(0);

		m_snapshot = new QNoteSnapshotWidget();
		if(note.resources.size() > 0)
			m_snapshot->setAttachment(true);

		layout->addItem(m_snapshot, 0, 0);
		layout->setAlignment(m_snapshot, Qt::AlignCenter);
                QFont titleFont;
                titleFont.setFamily(QString::fromUtf8("Nokia Sans"));
                titleFont.setPointSize(13);
                titleFont.setStyleStrategy(QFont::PreferAntialias);
                lTitle.setFont(titleFont);
		lTitle.setText(QString::fromUtf8(note.title.c_str()));
		//lTitle.setFixedWidth(150);
		//lTitle.setFixedHeight(30);
                lTitle.setContentsMargins(4, 0, 4, 0);

                QFontMetrics fm(titleFont);
                if(fm.boundingRect(lTitle.text()).width() < 150)
                    lTitle.setAlignment(Qt::AlignHCenter);

		layout->addItem(&lTitle, 1, 0);
                layout->setRowFixedHeight(1, 30);
		//TODO lDate.setStyleSheet("color: #37b4fc;font: 13px Nokia Sans;");
                lDate.setObjectName("lNoteDate");
                QFont dateFont;
                dateFont.setFamily(QString::fromUtf8("Nokia Sans"));
                dateFont.setPointSize(10);
                dateFont.setStyleStrategy(QFont::PreferAntialias);
                lDate.setFont(dateFont);
		lDate.setText(QDateTime::fromTime_t(note.created / 1000).toString("M/d/yy h:m AP"));
                lDate.setContentsMargins(4, 0, 4, 0);
		lDate.setAlignment(Qt::AlignHCenter);
		layout->addItem(&lDate, 2, 0);
                layout->setRowFixedHeight(2, 30);
		//setAttribute(Qt::WA_AcceptTouchEvents);
		//setFlat(true);
		QObject::connect(this, SIGNAL(clicked()), SLOT(selectNote()));
		QObject::connect(m_snapshot, SIGNAL(snapshotReady()), this, SLOT(storeSnapshot()));
	}

        QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const {
                return QSizeF(150, 180);
	}

        QSizeF	minimumSizeHint () const {
                return sizeHint(Qt::MinimumSize);
	}

	QNoteSnapshotWidget* snapshot() {
		return m_snapshot;
	}

	/*void setThumbnail(QByteArray& thumbnail) {
		snapshot()->render(thumbnail);
		emit noteRenderDone();
	}*/

	void setThumbnail(QPixmap* thumbnail) {
		snapshot()->render(thumbnail);
		emit noteRenderDone();
	}

	void setThumbnail(Guid guid) {
		snapshot()->render(guid);
		emit noteRenderDone();
	}

	Note& getNote() {
            return m_Note;
	}

public slots:
	void selectNote() {
		emit noteSelected(this);
	}

	void storeSnapshot() {
		/*QByteArray ba;
		QBuffer buf(&ba);
		buf.open(QIODevice::WriteOnly);
		m_snapshot->getSnapshotImage()->save(&buf, trUtf8("PNG"));
		QvernoteStorage::Instance()->setNoteThumbnail(m_Note, ba);*/
		emit insertImageCache(m_Note, m_snapshot->getSnapshotImage());
		emit noteRenderDone();
	}

signals:
	void noteSelected(QNoteWidget*);
	void noteRenderDone();
	void insertImageCache(Note&, QPixmap*);

private:
	QGraphicsGridLayout *layout;
	QNoteSnapshotWidget* m_snapshot;
	MLabel lTitle;
	MLabel lDate;
	Note	m_Note;
};

class QNoteGridView : public MWidget, public QAbstractNoteView
{
	Q_OBJECT

public:
	QNoteGridView(Guid& notebookGuid, MWidget* parent = 0)
        : MWidget(parent), QAbstractNoteView(notebookGuid), m_selectedItem(0), curCol(0), curRow(0) {
                //setPanDirection(Qt::Horizontal);
                noteGridLayout = new MLayout(this);
                MBasicLayoutAnimation* layoutAnim = new MBasicLayoutAnimation(noteGridLayout);
                //noteGridLayout->setAnimation(layoutAnim);
                noteGridLayoutPolicy = new MGridLayoutPolicy(noteGridLayout);

                //noteGridLayout->setContentsMargins(4, 4, 4, 4);
                //noteGridLayout->setSpacing(0);
		//TODO noteGridLayout->setSizeConstraint(QLayout::SetFixedSize);
		//noteGridLayout->setAlignment(Qt::AlignTop);

		QObject::connect(this, SIGNAL(noteSelected(Note&)), dynamic_cast<QNotesView*>(parentWidget()), SLOT(openNoteViewer(Note&)));
		QObject::connect(this, SIGNAL(noteLoadDone()), dynamic_cast<QNotesView*>(parentWidget()), SLOT(onNoteLoadDone()));
		QObject::connect(this, SIGNAL(noteLoadProgress()), dynamic_cast<QNotesView*>(parentWidget()), SLOT(onNoteLoadProgress()));

		QObject::connect(this, SIGNAL(tryLoadNextNote()), SLOT(loadNextNote()), Qt::QueuedConnection);
	}

	~QNoteGridView() {
		foreach(QPixmap* pImage, m_snapshotCacheMap) {
			delete pImage;
		}

		m_snapshotCacheMap.clear();
	}

	void redrawNotes(QString filterString = "") {
		QvernoteAPI* api = QvernoteAPI::Instance();
		Note note;
		curCol = curRow = 0;

		QGraphicsLayoutItem* i;
                while((i = noteGridLayout->itemAt(0)) != 0)
		{
			MWidget* w = (MWidget*)i->graphicsItem();
                        noteGridLayout->removeAt(0);
			w->deleteLater();
		}

		QRect screenGeometry = QApplication::desktop()->screenGeometry();
                qDebug() << screenGeometry;
		if(screenGeometry.width() > screenGeometry.height())
			maxCol = 5;
		else
			maxCol = 3;

		//t.start();

		m_filterString = filterString;
		if(api->getFirstNote(note))
		{
			createNoteWidget(note);
		}
		else
		{
			emit noteLoadDone();
		}
	}

	bool nextNote(Note& nextNote) {
            QGraphicsLayoutItem* item = noteGridLayout->itemAt(++m_selectedItem);
            if(item == NULL)
            {
                    m_selectedItem--;
                    return false;
            }

            QNoteWidget* w = (QNoteWidget*)item->graphicsItem();
            nextNote = w->getNote();
            return true;
	}

	bool prevNote(Note& prevNote) {
            if(m_selectedItem == 0)
                    return false;

            QGraphicsLayoutItem* item = noteGridLayout->itemAt(--m_selectedItem);

            if(item == NULL)
            {
                    m_selectedItem++;
                    return false;
            }

            QNoteWidget* w = (QNoteWidget*)item->graphicsItem();
            prevNote = w->getNote();
            return true;
	}

public slots:
	void selectNote(QNoteWidget* noteWidget) {
            m_selectedItem = noteGridLayout->indexOf(noteWidget);
            emit noteSelected(noteWidget->getNote());
	}

	void loadNextNote() {
		QvernoteAPI* api = QvernoteAPI::Instance();
		Note note;

		if(api->getNextNote(note))
		{
			createNoteWidget(note);
			emit noteLoadProgress();
		}
		else
		{
			emit noteLoadDone();
		}
	}

	void onInsertImageCache(Note& note, QPixmap* pImage) {
		m_snapshotCacheMap.insert(QString::fromStdString(note.guid), pImage);
	}

signals:
	void noteSelected(Note&);
	void tryLoadNextNote();
	void noteLoadDone();
	void noteLoadProgress();
	void progressDataUpdated(QString);

private:
	void createNoteWidget(Note& note) {
		QByteArray thumbnail;
		QPixmap*	thumbnailImage;

		if(QString::fromStdString(note.title).startsWith(m_filterString, Qt::CaseInsensitive))
		{
			QNoteWidget* w = new QNoteWidget(note);
			QObject::connect(w, SIGNAL(noteRenderDone()), this, SLOT(loadNextNote()));

			if((thumbnailImage = m_snapshotCacheMap.value(QString::fromStdString(note.guid))) == NULL)
			{
				if(QvernoteStorage::Instance()->getNoteThumbnail(note.guid, thumbnail))
				{
					thumbnailImage = new QPixmap();
					thumbnailImage->loadFromData(thumbnail);
					m_snapshotCacheMap.insert(QString::fromStdString(note.guid), thumbnailImage);
					w->setThumbnail(thumbnailImage);
				}
				else
				{
					QObject::connect(w, SIGNAL(insertImageCache(Note&, QPixmap*)), this, SLOT(onInsertImageCache(Note&, QPixmap*)));
					w->snapshot()->render(note.guid);
				}
			}
			else
			{
				w->setThumbnail(thumbnailImage);
			}

			//w->resize(150, 150);
                        //MeegoSupport::MSMessageBox("3. Here!", QString::number(curRow));
                        noteGridLayoutPolicy->addItem(w, curRow, curCol++);

			if(curCol >= maxCol)
			{
				curCol = 0;
				curRow++;
			}

			QObject::connect(w, SIGNAL(noteSelected(QNoteWidget*)), this, SLOT(selectNote(QNoteWidget*)));
		}
		else
		{
			emit tryLoadNextNote();
		}
	}

private:
        //QGraphicsGridLayout* noteGridLayout;
        MLayout* noteGridLayout;
        MGridLayoutPolicy* noteGridLayoutPolicy;
	int m_selectedItem;
	QString m_filterString;
	int curCol;
	int curRow;
	int maxCol;
	QMap<QString, QPixmap*> m_snapshotCacheMap;
	QTime t;
};

#endif /* QNOTEGRIDVIEW_H_ */
